/*@Author   S.Genikhov

/*Creation  Date 8/06/2010

/*Last modifed   8/06/2010

/*@Brief         Implementation of dinamical Array-Vector*/


#include <stdio.h>
#include <stdlib.h>

#include <Vector_inside.h>

#define   IN
#define OUT
#define N (6)
#define n_st (3)


/***********Vectro struc determination**************/

struct Vector{
    int  capacit;
    int  hwm;/*high warter mark*/
    int  lwm;/*low worter mark*/
    int  blck;
    int  nItems;
    void** data;
    };
/*****************************************************************************/
Vec_t* Vector_Creat()
{
     Vec_t* vec1=malloc(sizeof(Vec_t));
     vec1->blck=3;
     vec1->capacit=N;
     vec1->nItems=0;
     vec1->hwm=5;
     vec1->lwm=4;
     vec1->data=malloc(N*sizeof(void*));
    if(vec1->data==NULL)
    {
        return NULL;
    }
        return vec1;
}
/*******************************************************************************/

Vec_errors Vector_Add(Vec_t* _vec1,void* _data)
{
    if(_vec1==NULL)
    {
        return VEC_NOT_ACCEPT_VECTOR_Add  ;
    }

    if(_vec1->nItems >= _vec1->capacit-_vec1->hwm)
    {
        _vec1->capacit+=_vec1->blck;
        _vec1->data=(void**)realloc(_vec1->data,(_vec1->capacit)*sizeof(void*));
        if(_vec1->data==NULL)
        {
            return VEC_IMPOSSIBLE_ALLOCATE_NEW_ARRAY;
        }
    }
    _vec1->data[_vec1->nItems]=_data;
    ++_vec1->nItems;
    return 0;
}

Vec_errors Vector_Add_by_index(Vec_t* _vec1,void* _data,int _index)
{
    size_t      i;

    if(_vec1==NULL)
    {
        return VEC_NOT_ACCEPT_VECTOR_Add  ;
    }

    if(_vec1->nItems >= _vec1->capacit-_vec1->hwm)
    {
        _vec1->capacit+=_vec1->blck;
        _vec1->data=(void**)realloc(_vec1->data,(_vec1->capacit)*sizeof(void*));
        if(_vec1->data==NULL)
        {
            return VEC_IMPOSSIBLE_ALLOCATE_NEW_ARRAY;
        }
    }

    for (i=_vec1->nItems;i>_index;--i)
    {
        _vec1->data[i]=_vec1->data[i-1];
    }

    _vec1->data[_index]=_data;
    ++_vec1->nItems;
    return 0;
}


/*******************************************************************************/
Vec_errors Vector_Get(Vec_t* _vec1,OUT void** _data, int _index)

{
    if(_vec1==NULL)
    {
        return VEC_NOT_ACCEPT_VECTOR_Get;
    }
    if(_data==NULL)
    {
        return VEC_NOT_ACCEPT_DATA_Get ;
    }
    if (_index==_vec1->nItems)
    {
        return VEC_OUT_OF_BOUND_Get;
    }
    else
    {
        *_data=_vec1->data[_index];
    }

    return 0;
}

/*****************************************************************************************/

Vec_errors Vector_Set(Vec_t* _vec1,void* _new_data, int _index)
{
    if(_vec1==NULL)
    {
        return VEC_NOT_ACCEPT_VECTOR_Set;
    }
    if(_vec1->data==NULL)
    {
        return VEC_NOT_ACCEPT_DATA_Set;
    }
    if (_index>_vec1->nItems)
    {
        return VEC_OUT_OF_BOUND_Set;
    }

   _vec1->data[_index]=_new_data;
   return 0;
}

/*************************************************************************************/

Vec_errors Vector_Delete(Vec_t* _vec,int _index)/*Need also remove and delete*/
{
    size_t j;
    size_t temp;

    if (0==_vec->nItems)
    {
        return VEC_EMPTY_ARRAY_NOTHING_TO_DELETE;
    }

    if(_index<_vec->nItems)/*moove off all array*/
    {
        for(j=_index; j<_vec->nItems; ++j)
        {
            _vec->data[j]=_vec->data[j+1];
        }
    --_vec->nItems;
    }
    else
    {
          return VEC_OUT_OF_BOUND_Get;
    }

    temp=_vec->capacit-2*(_vec->lwm);/*Decreesing of vector capacit,
    if its capacitor greater than actual on 2*lwm*/

    if(_vec->nItems< temp && _vec->nItems>_vec->lwm)
    {
        _vec->capacit-=_vec->lwm;
        _vec->data=realloc(_vec->data,(_vec->capacit)*sizeof(_vec->data));

    }
    return 0;
}
void Vector_Destroy(Vec_t* _vec)
{
    size_t j;

    for(j=_vec->nItems;0<j;--j)
    {
        if(_vec->data[j-1]!=0)/*Problematic to 'free' null pointer*/
        {
            free(_vec->data[j-1]);
        }
    }
        free(_vec->data);
}


#ifdef vector_unit
void unitest();
Vec_errors regression_test();
Vec_errors Vector_error_description(Vec_errors err);
Vec_errors testing_Vector_Del(Vec_t* vec);
Vec_errors testing_Vector_Set(Vec_t* vec);
Vec_errors testing_Vector_Add(Vec_t* vec);
Vec_errors testing_Vector_Add(Vec_t* vec);
Vec_errors testing_Vector_Get();

int main()
{

    unitest();
    return 0;
}

void unitest()
{
    Vec_errors        err;
    err=regression_test();
    Vector_error_description(err);
}
/**********************************************************/
Vec_errors regression_test()
{
    Vec_t*       vec;
    Vec_errors err=0;
    int inter1;
    int inter2;
    int inter3;

    if(!(vec=Vector_Creat()))
    {
        return VEC_IMPOSSIBLE_ALLOCATE_NEW_ARRAY;
    }
    printf("Function Vector_Creat is o.k!\n");

    if((err=testing_Vector_Add(vec)))
    {
        return err;
    }
    inter1=*(((int**)(vec->data))[0]);
    inter2=*(((int**)(vec->data))[1]);
    inter3=*(((int**)(vec->data))[2]);
    printf("Function Vector_Add is o.k!\n");
    Vector_Destroy(vec);
    return err;
}

/***********************************************************/
Vec_errors Vector_error_description(Vec_errors err)
{
    switch (err)
    {
        case 0:
        printf("\nVec_All_IS_O_K \n"); break;
        case 1:
        printf("\nVec_IMPOSSIBLE_ALLOCATE_NEW_ARRAy\n"); break;
        case 10:
        printf("\nVec_OUT_OF_BOUND_Get\n");break;
        case 20:
        printf("\nVec_NOT_ACCEPT_VECTOR_Add\n");break;
        case 30:
        printf("\nVec_NOT_ACCEPT_DATA_Get\n");break;
        case 40:
        printf("\nVec_EMPTY_ARRAY_NOTHING_TO_DELETE\n");break;
        case 50:
        printf("\nVec_DATA_NOT_FITTED_Get\n");break;
        case 60:
        printf("\nNOT_ACCEPT_VECTOR_Get\n");break;
        case 70:
        printf("\nVec_NOT_ACCEPT_DATA_Set\n");break;
        case 80:
        printf("\nVec_NOT_ACCEPT_VECTOR_Setr\n");break;
        case 90:
        printf("\nVec_WRONG_DELET_ACTION \n");break;
        case 95:
        printf("\nVec_OUT_OF_BOUND_Set\n");break;

    }
    return err;
}
/***********************************************************
Vec_errors testing_Vector_Del(Vec_t* vec)
{
    int    a;
    size_t i;
    Vec_errors   err;

    for(i=0;i<5;++i)
    {
        a=vec->data[4];
        err=Vector_Delete(vec,4);
        if(vec->data[4]==a && err== 0)
        {
            return VEC_WRONG_DELET_ACTION ;
        }
    }
    return err;
}
/************************************************************
Vec_errors testing_Vector_Set(Vec_t* vec)
{
    Vec_errors err;

    vec->*data[3]=35;

    err=Vector_Set(vec,55,3);
    if (vec->data[3]==55 && err==0)
    {
        return 0;
    }
    else return err;
}
/***********************************************************/
Vec_errors testing_Vector_Add(Vec_t* vec)
{
    int* testingdata1=malloc(sizeof(int));
    int* testingdata2=malloc(sizeof(int));
    int* testingdata3=malloc(sizeof(int));

    Vec_errors err=0;
    /*Testing of adding to last index*/

        *testingdata1=rand()%20+10;
        *testingdata2=rand()%20+1000;
        *testingdata3=rand()%20+100;


        err=Vector_Add(vec,testingdata1);
        err=Vector_Add(vec,testingdata2);
        err=Vector_Add(vec,testingdata3);
        if (err)
        {
            return err;
        }
    return err;
}


Vec_errors testing_Vector_Get()
{
    int data;

    Vec_t*     vec;
    vec=Vector_Creat();
    testing_Vector_Add(vec);
    return Vector_Get(vec,&data,3);
}
#endif /*vector_unit*/




